"""
Configuration factory for creating HEMC configuration and routing commands based on JSON input.
根据 JSON 输入自动路由到对应函数，支持 energy_scan 等命令;
主要是为了方便配置 geant4 dll/so 路径， 以及 G4Dataset 路径
"""

import json
from pathlib import Path
from typing import Any, Dict, Optional

from pydantic import BaseModel

from ..scripts import energyscan, findpeaks, plotcsv
from ..utils.fingerprint import genfingerprint
from .models import (
    Geant4Config,
    HEMCConfig,
    ProjectPaths,
    SystemFingerprint,
)


class CommandInput(BaseModel):
    """Base model for command inputs."""

    call: str
    config_data: Optional[Dict[str, Any]] = None
    function_args: Optional[Dict[str, Any]] = None


def create_config_from_fingerprint(*args, **kwargs) -> HEMCConfig:
    """
    Create HEMC configuration based on system fingerprint.
    This handles platform-specific paths and environment setup.
    """
    fingerprint = genfingerprint()
    home_dir = Path.home()
    # print(f'fingerprint {fingerprint}')

    # Platform-specific configurations based on fingerprints
    system_configs = {
        "4eac38846a626f7a001d86647223149d": {  # ymy des fedora linux
            "g4_bin_dir": home_dir / "cpplibs/geant4v11.3.2/bin",
            "g4_data_dir": home_dir / "cpplibs/g4dataset11.3.2",
        },
        "846f672e2a83ffa1c115512d24fd25d3": {  # ymy des windows
            "g4_bin_dir": Path("C:/cppLibs/geant4-11.3.2/bin"),
            "g4_data_dir": Path("C:/cpplibs/g4dataset-11.3.2"),
        },
    }

    system_fingerprint = None
    if fingerprint in system_configs:
        config_data = system_configs[fingerprint]
        system_fingerprint = SystemFingerprint(
            fingerprint=fingerprint,
            g4bin_dir=config_data["g4_bin_dir"].resolve(),
            g4data_dir=config_data["g4_data_dir"].resolve(),
        )

    # Create project paths with the provided g4cxxdir
    # g4cxxdir = kwargs.pop('g4cxxdir', None)
    # if g4cxxdir is None:
    #     # Default to current approach if not specified
    #     g4cxxdir = Path(__file__).parent.parent.parent / "G4"

    project_paths = ProjectPaths(*args, **kwargs)
    # print(project_paths)
    ##============实例1: 自定义其他参数
    if False:
        g4config = Geant4Config(beam_on=12345)
        config = HEMCConfig(
            system_fingerprint=system_fingerprint,
            project_paths=project_paths,
            geant4=g4config,
        )

    config = HEMCConfig(
        system_fingerprint=system_fingerprint,
        project_paths=project_paths,
    )

    # Setup environment and directories
    config.setup_environment()
    config.create_required_directories()

    return config


def route_command(json_input: str) -> Any:
    """
    Route commands based on JSON input.
    The JSON should have a 'call' field that determines which function to execute.

    Args:
        json_input: JSON string containing the command and parameters

    Returns:
        Result of the function call
    """
    # Parse the JSON input
    input_data = json.loads(json_input)
    command_input = CommandInput(**input_data)

    # Import the functions here to avoid circular imports
    from ..scripts import test_configparse

    # Map command names to actual functions
    function_map = {
        "energy_scan": energyscan.main,
        "find_peaks": findpeaks.main,
        "postprocess": plotcsv.main,
        "test_configparse": test_configparse.main,
    }

    # Get the function to call
    if command_input.call not in function_map:
        raise ValueError(f"Unknown command: {command_input.call}")

    func = function_map[command_input.call]

    # Prepare arguments for the function
    # Check if config_data contains project paths info
    if command_input.config_data:
        # Extract path arguments from config_data
        g4cxxdir = command_input.config_data.get("g4cxxdir")
        postdir = command_input.config_data.get("postdir")

        if g4cxxdir and postdir:
            # Create configuration using the provided paths
            config = create_config_from_fingerprint(
                g4cxxdir=Path(g4cxxdir) if isinstance(g4cxxdir, str) else g4cxxdir,
                postdir=Path(postdir) if isinstance(postdir, str) else postdir,
            )

            # If we have a config created, we can pass additional function-specific args
            func_kwargs = command_input.function_args or {}
            return func(
                g4cxxdir=config.project_paths.g4cxxdir,
                postdir=config.project_paths.postdir,
                **func_kwargs,
            )
        else:
            # If config_data doesn't have the required paths, pass as-is
            func_kwargs = {
                **command_input.config_data,
                **(command_input.function_args or {}),
            }
    else:
        # If no config_data, use function_args or empty dict
        func_kwargs = command_input.function_args or {}

    # Call the function with the prepared arguments
    return func(**func_kwargs)
